<template>
  <div class="comments-section">
    <a-typography-title
      :level="4"
      style="margin-bottom: 10px"
    >
      评论
      {{ formatNumber(commentCount) }}
    </a-typography-title>

    <div class="comment-input">
      <a-textarea
        v-model:value="commentText"
        placeholder="请输入你的评论..."
        :rows="2"
        style="flex-grow: 1; resize: none"
      />

      <a-button
        type="primary"
        @click="publishComment"
      >
        发送
      </a-button>
    </div>

    <div class="comment-list">
      <div
        v-for="(comment, index) in commentList"
        :key="index"
        class="comment-item"
      >
        <a-avatar
          :size="40"
          :src="comment.avatarUrl"
          style="margin-right: 10px; cursor: pointer"
          @click="openUserProfile(comment.userId)"
        />
        <div class="comment-content">
          <strong
            style="cursor: pointer"
            @click="openUserProfile(comment.userId)"
            >{{ comment.nickname }}</strong
          >

          <p>{{ comment.content }}</p>

          <div class="comment-actions">
            <span class="timestamp">{{ timeFormat(comment.createTime) }}</span>

            <a-button
              type="link"
              size="small"
              @click="handleLikeComment(comment)"
              class="action-button"
              :style="comment.isLike && `color: #1890ff`"
            >
              <template #icon>
                <LikeOutlined />
              </template>
              {{ formatNumber(comment.likeCount) }}
            </a-button>

            <a-button
              type="link"
              size="small"
              @click="handleDislikeComment(comment)"
              class="action-button"
              :style="comment.isDislike && `color: #1890ff`"
            >
              <template #icon>
                <DislikeOutlined />
              </template>

              {{ formatNumber(comment.dislikeCount) }}
            </a-button>

            <a-button
              type="link"
              size="small"
              @click="openReplyInput(comment)"
              class="action-button"
            >
              回复
            </a-button>

            <a-button
              type="link"
              size="small"
              @click="openReportDialog(comment.id, comment.userId)"
              class="action-button"
            >
              举报
            </a-button>
          </div>

          <div
            v-if="comment.showReplyInput"
            class="reply-input"
          >
            <a-textarea
              v-model:value="replyContentText"
              placeholder="请输入回复评论..."
              :rows="2"
              style="flex-grow: 1; resize: none"
            />

            <a-button
              type="primary"
              size="small"
              @click="handleReplyComment(comment)"
              style="height: 50px; margin-left: 10px"
            >
              发送
            </a-button>
          </div>

          <div
            v-if="comment.replies?.length > 0"
            class="replies"
          >
            <div
              v-for="item in comment.replies"
              class="reply-item"
            >
              <a-avatar
                :size="30"
                :src="item.avatarUrl"
                style="margin-right: 10px; cursor: pointer"
                @click="openUserProfile(item.userId)"
              />

              <div class="reply-content">
                <strong
                  style="cursor: pointer"
                  @click="openUserProfile(item.userId)"
                  >{{ item.nickname }}</strong
                >
                回复
                <strong
                  style="cursor: pointer"
                  @click="openUserProfile(item.targetUserId)"
                  >{{ item.targetNickname }}</strong
                >

                <p>{{ item.content }}</p>

                <div class="reply-actions">
                  <span class="timestamp">{{ timeFormat(item.createTime) }}</span>

                  <a-button
                    type="link"
                    size="small"
                    @click="handleLikeCommentReply(item)"
                    class="action-button"
                    :style="item.isLike && `color: #1890ff`"
                  >
                    <template #icon><LikeOutlined /></template>
                    {{ formatNumber(item.likeCount) }}
                  </a-button>

                  <a-button
                    type="link"
                    size="small"
                    @click="handleDislikeCommentReply(item)"
                    class="action-button"
                    :style="item.isDislike && `color: #1890ff`"
                  >
                    <template #icon><DislikeOutlined /></template>
                    {{ formatNumber(item.dislikeCount) }}
                  </a-button>

                  <a-button
                    type="link"
                    size="small"
                    @click="openReplyInput(item, true, item.id)"
                    class="action-button"
                  >
                    回复
                  </a-button>

                  <a-button
                    type="link"
                    size="small"
                    @click="openReportDialog(item.id, item.userId)"
                    class="action-button"
                  >
                    举报
                  </a-button>
                </div>

                <div
                  v-if="item.showReplyInput"
                  class="nested-reply-input"
                >
                  <a-textarea
                    v-model:value="nestReplyContentText"
                    placeholder="请输入回复..."
                    :rows="2"
                    style="flex-grow: 1; resize: none"
                  />

                  <a-button
                    type="primary"
                    size="small"
                    @click="handleNestReplyComment(item, comment)"
                    style="height: 50px; margin-left: 10px"
                  >
                    发送
                  </a-button>
                </div>
              </div>
            </div>
          </div>

          <!-- 评论回复分页器 -->
          <Pagination
            v-if="comment.replyTotal > 5"
            style="margin: 20px 0; align-items: flex-start"
            v-model:page="comment.replyReqVO.pageNo"
            v-model:limit="comment.replyReqVO.pageSize"
            :total="comment.replyTotal"
            :is-small="true"
            @pagination="renderReplyComment(comment)"
          />
        </div>
      </div>
    </div>

    <!-- 评论分页器 -->
    <Pagination
      v-model:page="commentQuery.pageNo"
      v-model:limit="commentQuery.pageSize"
      :total="commentTotal"
      @pagination="getCommentData"
    />

    <!-- 举报对话框 -->
    <a-modal
      v-model:visible="reportModalVisible"
      title="举报内容"
      ok-text="提交"
      cancel-text="取消"
      @ok="submitReport"
      @cancel="closeReportDialog"
      :zIndex="1050"
      :centered="true"
      :keyboard="false"
      :mask-closable="false"
    >
      <a-checkbox-group
        v-model:value="selectedReasons"
        style="width: 100%"
      >
        <a-row :gutter="[16, 16]">
          <a-col
            :span="12"
            v-for="reason in reportOptions"
          >
            <a-checkbox :value="reason.label">{{ reason.label }}</a-checkbox>
          </a-col>
          <a-col :span="12">
            <a-checkbox value="other">其他</a-checkbox>
          </a-col>
        </a-row>
      </a-checkbox-group>
      <div
        v-if="selectedReasons.includes('other')"
        style="margin: 10px 0 40px 0"
      >
        <a-textarea
          v-model:value="otherReasonText"
          placeholder="请输入具体原因..."
          :rows="4"
          :maxlength="500"
          show-count
          style="resize: none"
        />
      </div>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { LikeOutlined, DislikeOutlined } from '@ant-design/icons-vue'
import type { CvCommentReqVO, CvCommentRespVO, CvCommentSaveReqVO } from '@/types/comment'
import { createComment, getCommentPage } from '@/api/comment'
import dayjs from 'dayjs'
import { getAccessToken } from '@/utils/auth'
import { message } from 'ant-design-vue'
import { cancelCommentLike, saveCommentLike } from '@/api/comment/like'
import { cancelCommentDislike, saveCommentDislike } from '@/api/comment/dislike'
import { CvCommentReplyRespVO, CvCommentReplySaveReqVO } from '@/types/commentReply'
import { createCommentReply, getCommentReplyPage } from '@/api/commentReply'
import { cancelCommentReplyDislike, saveCommentReplyDislike } from '@/api/commentReply/dislike'
import { cancelCommentReplyLike, saveCommentReplyLike } from '@/api/commentReply/like'
import { reportOptions, reportType } from '@/utils/options'
import { CvReportSaveReqVO } from '@/types/report'
import { useUserStore } from '@/store/modules/user'
import { saveReport } from '@/api/report'

/**
 * 视频编号
 */
const videoId = defineModel('videoId')

/**
 * 评论数量
 */
const commentCount = defineModel('commentCount')

/**
 * 评论内容
 */
const commentText = ref('')

/**
 * 评论分页查询
 */
const commentQuery = ref<CvCommentReqVO>(<CvCommentReqVO>{
  videoId: videoId.value,
  pageNo: 1,
  pageSize: 10
})

/**
 * 评论分页数据
 */
const commentList = ref<CvCommentRespVO[]>([])
const commentTotal = ref(0)

watch(
  () => videoId.value,
  () => {
    commentQuery.value.videoId = videoId.value
    getCommentData()
  }
)

/**
 * 评论数量格式化
 */
const formatNumber = (num: number | string) => {
  if (!num) {
    return 0
  }

  if (num >= 1000 && num < 10000) {
    return (num / 1000).toFixed(1) + 'K'
  } else if (num >= 10000) {
    return (num / 10000).toFixed(1) + 'W'
  } else {
    return num.toString()
  }
}

/**
 * 获取评论分页数据
 */
const getCommentData = async () => {
  const res = await getCommentPage(commentQuery.value)
  commentList.value = res.list
  commentTotal.value = res.total

  // 手动隐藏回复输入框并获取回复列表
  for (const item of commentList.value) {
    item.showReplyInput = false
    item.replies = []
    item.replyReqVO = {
      commentId: item.id,
      pageNo: 1,
      pageSize: 5
    }
    await renderReplyComment(item)
  }
}

/**
 * 时间格式化
 */
const timeFormat = (time: string) => {
  if (time) {
    return dayjs(time).format('YYYY-MM-DD HH:mm:ss')
  }
  return ''
}

/**
 * 发布评论
 */
const publishComment = async () => {
  if (!getAccessToken()) {
    message.error('请登录')
    return
  }

  if (commentText.value.trim()) {
    const data: CvCommentSaveReqVO = <CvCommentSaveReqVO>{
      videoId: videoId.value,
      content: commentText.value
    }
    try {
      await createComment(data)
      commentText.value = ''
      await getCommentData()

      let count = commentCount.value
      commentCount.value = count + 1
    } catch (error) {
      console.error('发布评论失败：', error)
    }
  }
}

/**
 * 点赞评论
 */
const handleLikeComment = async (comment: CvCommentRespVO) => {
  if (!getAccessToken()) {
    message.error('请登录')
    return
  }

  // 如果点了踩，先取消踩
  if (comment.isDislike) {
    await handleDislikeComment(comment)
  }

  try {
    if (comment.isLike) {
      await cancelCommentLike(comment.id)
      commentList.value.forEach((item: CvCommentRespVO) => {
        if (item.id === comment.id) {
          item.isLike = false
          item.likeCount -= 1
        }
      })
    } else {
      await saveCommentLike(comment.id)
      commentList.value.forEach((item: CvCommentRespVO) => {
        if (item.id === comment.id) {
          item.isLike = true
          item.likeCount += 1
        }
      })
    }
  } catch (error) {
    console.error('点赞评论失败：', error)
  }
}

/**
 * 踩评论
 */
const handleDislikeComment = async (comment: CvCommentRespVO) => {
  if (!getAccessToken()) {
    message.error('请登录')
    return
  }

  if (comment.isLike) {
    await handleLikeComment(comment)
  }

  try {
    if (comment.isDislike) {
      await cancelCommentDislike(comment.id)
      commentList.value.forEach((item: CvCommentRespVO) => {
        if (item.id === comment.id) {
          item.isDislike = false
          item.dislikeCount -= 1
        }
      })
    } else {
      await saveCommentDislike(comment.id)
      commentList.value.forEach((item: CvCommentRespVO) => {
        if (item.id === comment.id) {
          item.isDislike = true
          item.dislikeCount += 1
        }
      })
    }
  } catch (error) {
    console.error('踩评论失败：', error)
  }
}

/**
 * 跳转到用户主页
 */
const openUserProfile = (userId: number) => {
  window.open(`/profile?userId=${userId}`)
}

// ==================== 回复评论 ====================

const replyContentText = ref('')
const nestReplyContentText = ref('')

/**
 * 获取回复评论分页数据
 */
const renderReplyComment = async (comment: CvCommentRespVO) => {
  try {
    const res = await getCommentReplyPage(comment.replyReqVO)
    comment.replies = res.list
    comment.replyTotal = res.total

    if (comment.replyTotal > 0) {
      comment.replies.forEach((item: CvCommentReplyRespVO) => {
        item.showReplyInput = false
      })
    }
  } catch (error) {
    console.error('获取回复评论分页数据失败：', error)
  }
}

/**
 * 开启回复输入框
 */
const openReplyInput = (
  comment: CvCommentRespVO | CvCommentReplyRespVO,
  isReply: boolean = false,
  replayId: number = 0
) => {
  if (isReply) {
    commentList.value.forEach((item: CvCommentRespVO) => {
      item.replies.forEach((element: CvCommentReplyRespVO) => {
        element.showReplyInput = element.id === replayId
      })
    })

    commentList.value.forEach((item: CvCommentRespVO) => {
      item.showReplyInput = false
    })
  } else {
    commentList.value.forEach((item: CvCommentRespVO) => {
      item.showReplyInput = item.id === comment.id
    })

    commentList.value.forEach((item: CvCommentRespVO) => {
      item.replies.forEach((element: CvCommentReplyRespVO) => {
        element.showReplyInput = false
      })
    })
  }

  replyContentText.value = ''
  nestReplyContentText.value = ''
}

/**
 * 回复评论
 */
const handleReplyComment = async (comment: CvCommentRespVO) => {
  if (!getAccessToken()) {
    message.error('请登录')
    return
  }

  if (replyContentText.value.trim()) {
    const data: CvCommentReplySaveReqVO = <CvCommentReplySaveReqVO>{
      commentId: comment.id,
      targetUserId: comment.userId,
      content: replyContentText.value
    }
    try {
      await createCommentReply(data)
      replyContentText.value = ''
      commentList.value.forEach((item: CvCommentRespVO) => {
        if (item.id === comment.id) {
          item.showReplyInput = false
        }
      })
      await renderReplyComment(comment)

      let count = commentCount.value
      commentCount.value = count + 1
    } catch (error) {
      console.error('回复评论失败：', error)
    }
  }
}

/**
 * 回复回复评论
 */
const handleNestReplyComment = async (reply: CvCommentReplyRespVO, comment: CvCommentRespVO) => {
  if (!getAccessToken()) {
    message.error('请登录')
    return
  }

  if (nestReplyContentText.value.trim()) {
    const data: CvCommentReplySaveReqVO = <CvCommentReplySaveReqVO>{
      commentId: comment.id,
      targetUserId: reply.userId,
      content: nestReplyContentText.value
    }
    try {
      await createCommentReply(data)
      nestReplyContentText.value = ''
      commentList.value.forEach((item: CvCommentRespVO) => {
        item.replies.forEach((element: CvCommentReplyRespVO) => {
          if (element.id === reply.id) {
            element.showReplyInput = false
          }
        })
      })
      await renderReplyComment(comment)

      let count = commentCount.value
      commentCount.value = count + 1
    } catch (error) {
      console.error('回复评论失败：', error)
    }
  }
}

/**
 * 点赞回复评论
 */
const handleLikeCommentReply = async (reply: CvCommentReplyRespVO) => {
  if (!getAccessToken()) {
    message.error('请登录')
    return
  }

  // 如果点了踩，先取消踩
  if (reply.isDislike) {
    await handleDislikeCommentReply(reply)
  }

  try {
    if (reply.isLike) {
      await cancelCommentReplyLike(reply.id)
      commentList.value.forEach((item: CvCommentRespVO) => {
        item.replies.forEach((element: CvCommentReplyRespVO) => {
          if (element.id === reply.id) {
            element.isLike = false
            element.likeCount -= 1
          }
        })
      })
    } else {
      await saveCommentReplyLike(reply.id)
      commentList.value.forEach((item: CvCommentRespVO) => {
        item.replies.forEach((element: CvCommentReplyRespVO) => {
          if (element.id === reply.id) {
            element.isLike = true
            element.likeCount += 1
          }
        })
      })
    }
  } catch (error) {
    console.error('点赞回复评论失败：', error)
  }
}

/**
 * 踩评论
 */
const handleDislikeCommentReply = async (reply: CvCommentReplyRespVO) => {
  if (!getAccessToken()) {
    message.error('请登录')
    return
  }

  if (reply.isLike) {
    await handleLikeCommentReply(reply)
  }

  try {
    if (reply.isDislike) {
      await cancelCommentReplyDislike(reply.id)
      commentList.value.forEach((item: CvCommentRespVO) => {
        item.replies.forEach((element: CvCommentReplyRespVO) => {
          if (element.id === reply.id) {
            element.isDislike = false
            element.dislikeCount -= 1
          }
        })
      })
    } else {
      await saveCommentReplyDislike(reply.id)
      commentList.value.forEach((item: CvCommentRespVO) => {
        item.replies.forEach((element: CvCommentReplyRespVO) => {
          if (element.id === reply.id) {
            element.isDislike = true
            element.dislikeCount += 1
          }
        })
      })
    }
  } catch (error) {
    console.error('踩回复评论失败：', error)
  }
}

// ==================== 举报评论 ====================

const userStore = useUserStore()
const reportModalVisible = ref(false)
const selectedReasons = ref<string[]>([])
const otherReasonText = ref('')
const childrenId = ref<any>(null)
const targetUserId = ref<any>(null)

const openReportDialog = (businessId: number, userId: number) => {
  if (!getAccessToken()) {
    message.error('请登录')
    return
  }

  if (userStore.getUserId == userId) {
    message.error('你不能举报自己')
    return
  }

  reportModalVisible.value = true
  selectedReasons.value = []
  otherReasonText.value = ''
  childrenId.value = businessId
  targetUserId.value = userId
}

const submitReport = async () => {
  if (childrenId.value) {
    let reasons = ''
    for (let i = 0; i < selectedReasons.value.length; i++) {
      if (selectedReasons.value[i] !== 'other') {
        reasons = reasons + (i + 1) + '. ' + selectedReasons.value[i] + '\n'
      } else if (otherReasonText.value) {
        reasons = reasons + selectedReasons.value.length + '. ' + otherReasonText.value
      }
    }

    if (!reasons) {
      message.error('请选择举报理由')
      return
    }

    await saveReport(<CvReportSaveReqVO>{
      id: null,
      reason: reasons,
      reportType: reportType[1].value,
      reportUserId: userStore.getUserId,
      targetUserId: targetUserId.value,
      childrenId: childrenId.value
    })
    message.success('举报成功，请待客服审核处理')
    closeReportDialog()
  }
}

const closeReportDialog = () => {
  reportModalVisible.value = false
  selectedReasons.value = []
  otherReasonText.value = ''
  childrenId.value = null
  targetUserId.value = null
}
</script>

<style scoped>
/* 整体样式 */
.comments-section {
  margin-top: 20px;
}

/* 评论输入区域 */
.comment-input {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  margin-bottom: 20px;
}

.comment-input .ant-btn {
  height: 50px;
  margin-left: 10px;
}

/* 评论列表 */
.comment-list {
  margin-top: 20px;
}

/* 单个评论项 */
.comment-item {
  display: flex;
  margin-bottom: 20px;
}

/* 评论内容 */
.comment-content {
  flex-grow: 1;
}

.comment-content p {
  margin-bottom: 0; /* 移除底部外边距 */
}

/* 评论操作按钮 */
.comment-actions {
  display: flex;
  align-items: center;
  font-size: 12px;
  color: #999;
  margin-top: 5px;
}

.comment-actions .timestamp {
  margin-right: 10px;
  color: #999;
  cursor: default;
}

.comment-actions .action-button {
  color: inherit;
  transition: color 0.3s;
}

.comment-actions .action-button:hover {
  color: #1890ff;
}

/* 子回复 */
.replies {
  margin-top: 10px; /* 添加间距 */
}

/* 单个子回复项 */
.reply-item {
  display: flex;
  margin-bottom: 10px;
}

/* 子回复内容 */
.reply-content {
  flex-grow: 1;
}

.reply-content p {
  margin-top: 5px; /* 确保回复内容在“xxx 回复 xxx”下面 */
  margin-bottom: 0; /* 移除底部外边距 */
}

/* 子回复操作按钮 */
.reply-actions {
  display: flex;
  align-items: center;
  font-size: 12px;
  color: #999;
  margin-top: 5px;
}

.reply-actions .timestamp {
  margin-right: 10px;
  color: #999;
  cursor: default;
}

.reply-actions .action-button {
  color: inherit;
  transition: color 0.3s;
}

.reply-actions .action-button:hover {
  color: #1890ff;
}

/* 回复输入框 */
.reply-input,
.nested-reply-input {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  margin-top: 10px;
}
</style>
